﻿// Copyright (c) Inossem. All rights reserved.
// Licensed under the LGPL-3.0 license. See LICENSE file in the project root for full license information.
using DWF.Studio.Custom;
using DWF.Studio.ISerivces;
using DWF.Studio.NuGetManagement;
using DWF.Studio.Project;
using DWF.Studio.Services;
using DWF.Studio.Share.Log;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Resources.Tools;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;

namespace DWF.Studio.Views
{
    /// <summary>
    /// 包列表
    /// </summary>
    public partial class UCtrlPackageList : UserControl
    {
        /// <summary>
        /// 包管理器
        /// </summary>
        private IPackageManager _nugetPackageManager = null;

        /// <summary>
        /// 工程管理器
        /// </summary>
        private ProjectManager _projectManager = null;

        /// <summary>
        /// 
        /// </summary>
        private IConfigService _configService = null;
        private string _searchStr="";

        /// <summary>
        /// 页索引
        /// </summary>
        private int _pageIndex = 0;

        /// <summary>
        /// 每页数量
        /// </summary>
        private int _pageCount = 10;

        private ObservableCollection<NugetPackageWrap> _obsNugetPackages = new ObservableCollection<NugetPackageWrap>();

        public UCtrlPackageList()
        {
            InitializeComponent();

            if (!DesignerProperties.GetIsInDesignMode(this))
            {
                init();
            }
        }
        public async Task<bool> RefreshPage(string packageName="")
        {
            _obsNugetPackages.Clear();
            init();
            _searchStr = packageName;
            switch (WindowPackageManagement.packagePageStatus)
            {
                case PackagePageStatus.networkPackageShow:await loadNetwork();break;
                case PackagePageStatus.allNetworkPackageShow:await loadNetwork();break;
                case PackagePageStatus.customPackageShow:await loadNetwork(); break;
                case PackagePageStatus.localPackageShow:await loadNetwork();break;
                default:await loadDepencyPackages();break;
            }
            
            return true;
        }
        /// <summary>
        /// 初始化
        /// </summary>
        private void init()
        {
            _configService = new ConfigService();
            var config = _configService.LoadSysConfig();//加载配置文件

            var packageUri = config.GetStablePackageUri();//nuget地址
            switch (WindowPackageManagement.packagePageStatus)
            {
                case PackagePageStatus.networkPackageShow:
                    _nugetPackageManager = new PackageManager(packageUri, GetPackageStatus.officialPackageSource); break;
                case PackagePageStatus.customPackageShow:
                    _nugetPackageManager = new PackageManager(packageUri, GetPackageStatus.customPackageSource);break;
                case PackagePageStatus.localPackageShow:
                    _nugetPackageManager = new PackageManager(packageUri, GetPackageStatus.localPackagesSource);break;
                case PackagePageStatus.packageSourceManagerShow:
                    _nugetPackageManager = new PackageManager(packageUri, GetPackageStatus.localPackagesSource);break;
                default:
                    _nugetPackageManager = new PackageManager(packageUri);break;
            }
            _projectManager = ProjectManager.Instance;

            this.lbPackages.ItemsSource = _obsNugetPackages;
        }

        /// <summary>
        /// 控件加载
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private async void UserControl_Loaded(object sender, RoutedEventArgs e)
        {
            if (!DesignerProperties.GetIsInDesignMode(this))
            {
                GlobalActionHandler.PackageWrapPrechange += PackageWrapStatusPrechange;
            }
            
            if (!string.IsNullOrWhiteSpace(_searchStr))
            {
                TextBox txtSearchBox = WPFExtensionMethods.FindVisualChild<TextBox>(FindName("txtSearch") as DependencyObject);
                txtSearchBox.Text = _searchStr;
                await loadDepencyPackages();
            }
        }

        /// <summary>
        /// 控件卸载
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void UserControl_Unloaded(object sender, RoutedEventArgs e)
        {
            GlobalActionHandler.PackageWrapPrechange -= PackageWrapStatusPrechange;
        }

        /// <summary>
        /// 下一页
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private async void BtnGoToNextPage_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                var index = _pageIndex + _pageCount;
                TextBox txtSearchBox = WPFExtensionMethods.FindVisualChild<TextBox>(FindName("txtSearch") as DependencyObject);
                var packages = await _nugetPackageManager.SearchPackagesAsync(txtSearchBox.Text, index, _pageCount);
                if (packages.Count() > 0)
                {
                    _obsNugetPackages.Clear();
                    foreach (var package in packages)
                    {
                        _obsNugetPackages.Add(new NugetPackageWrap(package));
                    }
                    _pageIndex = index;

                    txtPageNum.Text = Convert.ToString(_pageIndex / _pageCount + 1);
                }
            }
            catch (Exception ex)
            {
                LogHelper.Error(ex.ToString());
            }
        }

        /// <summary>
        /// 上一页
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private async void BtnGoToPreviousPage_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                var index = _pageIndex - _pageCount;
                TextBox txtSearchBox = WPFExtensionMethods.FindVisualChild<TextBox>(FindName("txtSearch") as DependencyObject);
                if (index >= 0)
                {
                    var packages = await _nugetPackageManager.SearchPackagesAsync(txtSearchBox.Text, index, _pageCount);
                    if (packages.Count() > 0)
                    {
                        _obsNugetPackages.Clear();
                        foreach (var package in packages)
                        {
                            _obsNugetPackages.Add(new NugetPackageWrap(package));
                        }
                        _pageIndex = index;
                        txtPageNum.Text = Convert.ToString(_pageIndex / _pageCount + 1);
                    }
                }
            }
            catch (Exception ex)
            {
                LogHelper.Error(ex.ToString());
            }
        }

        /// <summary>
        /// 选择某一项
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void LbPackages_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            var package = this.lbPackages.SelectedItem as NugetPackageWrap;
            if (package != null)
            {
                GlobalActionHandler.PackageSelected?.Invoke(new TagEventArgs<NugetPackageWrap>(package));
            }
        }

        private void Image_ImageFailed(object sender, ExceptionRoutedEventArgs e)
        {
            ((Image)sender).Source = StaticResource.DefaultNugetImage;
        }

        /// <summary>
        /// 文本框回车
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private async void TxtSearch_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.Enter)
            {
                if (WindowPackageManagement.packagePageStatus==PackagePageStatus.installedPackageShow)
                {
                    await loadDepencyPackages();
                }
                else
                {
                    await loadNetwork();
                }
            }
        }
        /// <summary>
        /// 点击按钮改变当前包状态图标
        /// </summary>
        /// <param name="e"></param>
        private void PackageWrapStatusPrechange(TagEventArgs<NugetPackageWrap> e)
        {
            var packageStatus = WindowPackageManagement._currentPackageWrapList.Where(p => p.Id == e.Tag.Id).FirstOrDefault();
            var _nugetPackages = _obsNugetPackages.ToList();
            var dependonPackages = _projectManager.GetDependOnPackageInfos();//获取项目依赖包
            if (dependonPackages != null)//已经安装
            {
                foreach(var item in dependonPackages)
                {
                    if (_nugetPackages.Where(o => o.Id == item.Id).FirstOrDefault() != null)
                        _nugetPackages.Where(o => o.Id == item.Id).FirstOrDefault().StatusIcon = Visibility.Visible;
                }
            }
            if (packageStatus == null)
            {
                _nugetPackages.Where(o => o.Id == e.Tag.Id).FirstOrDefault().IsUpdate = Visibility.Hidden;
                _nugetPackages.Where(o => o.Id == e.Tag.Id).FirstOrDefault().IsDelete = Visibility.Hidden;
                _nugetPackages.Where(o => o.Id == e.Tag.Id).FirstOrDefault().IsInstall = Visibility.Hidden;
                _nugetPackages.Where(o => o.Id == e.Tag.Id).FirstOrDefault().ButtonIcon = Visibility.Hidden;
            }
            else
            {
                if (e.Tag.PackageOperationType == PackageOperationType.UnInstall)
                {
                    _nugetPackages.Where(o => o.Id == e.Tag.Id).FirstOrDefault().IsDelete = Visibility.Visible;
                    _nugetPackages.Where(o => o.Id == e.Tag.Id).FirstOrDefault().IsUpdate = Visibility.Hidden;
                    _nugetPackages.Where(o => o.Id == e.Tag.Id).FirstOrDefault().IsInstall = Visibility.Hidden;
                }
                else if (e.Tag.PackageOperationType == PackageOperationType.Update)
                {
                    _nugetPackages.Where(o => o.Id == e.Tag.Id).FirstOrDefault().IsUpdate = Visibility.Visible;
                    _nugetPackages.Where(o => o.Id == e.Tag.Id).FirstOrDefault().IsDelete = Visibility.Hidden;
                    _nugetPackages.Where(o => o.Id == e.Tag.Id).FirstOrDefault().IsInstall = Visibility.Hidden;
                }
                else if (e.Tag.PackageOperationType == PackageOperationType.Install)
                {
                    _nugetPackages.Where(o => o.Id == e.Tag.Id).FirstOrDefault().IsInstall = Visibility.Visible;
                    _nugetPackages.Where(o => o.Id == e.Tag.Id).FirstOrDefault().IsUpdate = Visibility.Hidden;
                    _nugetPackages.Where(o => o.Id == e.Tag.Id).FirstOrDefault().IsDelete = Visibility.Hidden;
                }
                _nugetPackages.Where(o => o.Id == e.Tag.Id).FirstOrDefault().ButtonIcon = Visibility.Visible;
            }
            _obsNugetPackages.Clear();
            _nugetPackages.ForEach(p => _obsNugetPackages.Add(p));
        }
        /// <summary>
        /// 加载工程依赖包
        /// </summary>
        /// <returns></returns>
        private async Task loadDepencyPackages()
        {
            try
            {
                _pageIndex = 0;
                _obsNugetPackages.Clear();
                TextBox txtSearchBox = WPFExtensionMethods.FindVisualChild<TextBox>(FindName("txtSearch") as DependencyObject);
              
                this.emptyPackageList.Visibility = Visibility.Visible;
                var dependonPackages = _projectManager.GetDependOnPackageInfos();
                if (dependonPackages != null)
                {
                    var baseDirectory = new DirectoryInfo(AppDomain.CurrentDomain.BaseDirectory).Parent.FullName;
                    var installPath = Path.Combine(baseDirectory, StaticResource.Activities);//安装路径 

                    foreach (var dependonPackage in dependonPackages)
                    {
                        var activitie = dependonPackage.Id + "." + dependonPackage.Version;
                        var activitiepath = installPath + "\\" + activitie + "\\" + activitie + ".nupkg";
                        var packageProxy = await _nugetPackageManager.GetLocalRoutePackageByIdAsync(activitiepath);
                        if (packageProxy == null)
                            continue;
                        var nugetPackageWrap = new NugetPackageWrap(packageProxy);
                        if (txtSearchBox != null && !string.IsNullOrWhiteSpace(txtSearchBox.Text))
                        {
                            if (!dependonPackage.Id.ToLower().Contains(txtSearchBox.Text.ToLower()) && !nugetPackageWrap.Description.ToLower().Contains(txtSearchBox.Text.ToLower()))
                            {
                                continue;
                            }
                        }
                        if (packageProxy != null)
                        {
                            nugetPackageWrap.StatusIcon = Visibility.Visible;
                            var packageStatus = WindowPackageManagement._currentPackageWrapList.Where(p => p.Id == packageProxy.Id).FirstOrDefault();
                            if (packageStatus != null)
                            {
                                nugetPackageWrap = changeImageStatus(nugetPackageWrap, packageStatus.PackageOperationType);
                               
                                nugetPackageWrap.ButtonIcon = Visibility.Visible;
                            }
                            this.emptyPackageList.Visibility = Visibility.Collapsed;

                            _obsNugetPackages.Add(nugetPackageWrap);
                        }
                        else
                        {
                            nugetPackageWrap.StatusIcon = Visibility.Visible;
                            var packageStatus = WindowPackageManagement._currentPackageWrapList.Where(p => p.Id == nugetPackageWrap.Id).FirstOrDefault();
                            if (packageStatus != null)
                            {
                                if (packageStatus.PackageOperationType == PackageOperationType.UnInstall)
                                {
                                    nugetPackageWrap.IsDelete = Visibility.Visible;
                                    nugetPackageWrap.IsUpdate = Visibility.Hidden;
                                    nugetPackageWrap.IsInstall = Visibility.Hidden;
                                }
                                else if (packageStatus.PackageOperationType == PackageOperationType.Update)
                                {
                                    nugetPackageWrap.IsUpdate = Visibility.Visible;
                                    nugetPackageWrap.IsDelete = Visibility.Hidden;
                                    nugetPackageWrap.IsInstall = Visibility.Hidden;
                                }
                                nugetPackageWrap.ButtonIcon = Visibility.Visible;
                            }
                            this.emptyPackageList.Visibility = Visibility.Collapsed;

                            _obsNugetPackages.Add(nugetPackageWrap);
                        }
                    }
                    Selection();
                }
            }
            catch (Exception ex)
            {
                LogHelper.Error(ex.ToString());
            }
            await this.Dispatcher.InvokeAsync(async () =>
            {
                await getPackageUpgradeAsync();
            }, System.Windows.Threading.DispatcherPriority.ApplicationIdle);
        }

        /// <summary>
        /// 加载网络包
        /// </summary>
        /// <returns></returns>
        private async Task loadNetwork()
        {
            try
            {
                _pageIndex = 0;
                IEnumerable<NuGetPackage> packages = null;
                TextBox txtSearchBox = WPFExtensionMethods.FindVisualChild<TextBox>(FindName("txtSearch") as DependencyObject);
  
                try
                {
                    packages = await _nugetPackageManager.SearchPackagesAsync(txtSearchBox.Text, _pageIndex, _pageCount);
                }
                catch (Exception ex)
                {
                    throw new CustomException(LocalizationProvider.GetLocalizedString("UCtrlPackageList_MsgBox_Msg_LoadPackages"), ex);
                }
                finally
                {
                    _obsNugetPackages.Clear();
                    this.emptyPackageList.Visibility = Visibility.Visible;
                }
                var dependonPackages = _projectManager.GetDependOnPackageInfos();//获取项目依赖包
                foreach (var package in packages)
                {
                    var packageStatus = WindowPackageManagement._currentPackageWrapList.Where(p => p.Id == package.Id).FirstOrDefault();//获取要执行的包

                    var nugetPackageWrap = new NugetPackageWrap(package);

                    if (txtSearchBox != null && !string.IsNullOrWhiteSpace(txtSearchBox.Text))
                    {
                        if (!package.Id.ToLower().Contains(txtSearchBox.Text.ToLower()) && !package.Description.ToLower().Contains(txtSearchBox.Text.ToLower()))
                        {
                            continue;
                        }
                    }
                    if (dependonPackages != null)//已经安装
                    {
                        if (dependonPackages.Where(o => o.Id == nugetPackageWrap.Id).FirstOrDefault() != null)
                        {
                            nugetPackageWrap.StatusIcon = Visibility.Visible;
                        }
                    }
                    if (packageStatus != null)
                    {
                        nugetPackageWrap = changeImageStatus(nugetPackageWrap, packageStatus.PackageOperationType);
                        
                        nugetPackageWrap.ButtonIcon = Visibility.Visible;
                    }
                    //已安装的选项，如果项目依赖不存在则返回  不添加到列表
                    if (WindowPackageManagement.packagePageStatus == PackagePageStatus.installedPackageShow && dependonPackages.Where(o => o.Id == nugetPackageWrap.Id && o.Version == nugetPackageWrap.Version).FirstOrDefault() == null)
                    {
                        continue;
                    }
                    this.emptyPackageList.Visibility = Visibility.Collapsed;
                    _obsNugetPackages.Add(nugetPackageWrap);
                }
                txtPageNum.Text = Convert.ToString(_pageIndex / _pageCount + 1);
            }
            catch (Exception ex)
            {
                LogHelper.Error(ex.ToString());
            }
            await this.Dispatcher.InvokeAsync(async () =>
            {
                await getPackageUpgradeAsync();
            }, System.Windows.Threading.DispatcherPriority.ApplicationIdle);
        }
        
        /// <summary>
        /// 删除选项
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Button_Click(object sender, RoutedEventArgs e)
        {
            var item = ((ListBoxItem)lbPackages.ContainerFromElement((System.Windows.Controls.Button)sender)).Content as NugetPackageWrap;
            var selectNugetPackageWrap = WindowPackageManagement._currentPackageWrapList.Where(o => o.Id == item.Id).FirstOrDefault();
            if (selectNugetPackageWrap == null)
                return;
            WindowPackageManagement._currentPackageWrapList.Remove(selectNugetPackageWrap);
            this.PackageWrapStatusPrechange(new TagEventArgs<NugetPackageWrap>(selectNugetPackageWrap));

            GlobalActionHandler.PackageSelected?.Invoke(new TagEventArgs<NugetPackageWrap>(item as NugetPackageWrap));
        }
        /// <summary>
        /// 滑动条触底加载事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private async void lbPackages_ScrollChanged(object sender, ScrollChangedEventArgs e)
        {
            try
            {
                ScrollViewer viewer = e.OriginalSource as ScrollViewer;
                if (viewer == null) return;
                double bottomOffset = viewer.ExtentHeight - viewer.VerticalOffset - viewer.ViewportHeight;
                if (viewer.VerticalOffset > 0 && bottomOffset == 0)
                {
                    _pageIndex++;
                    IEnumerable<NuGetPackage> packages = null;
                    TextBox txtSearchBox = WPFExtensionMethods.FindVisualChild<TextBox>(FindName("txtSearch") as DependencyObject);
                    try
                    {
                        packages = await _nugetPackageManager.SearchPackagesAsync(txtSearchBox.Text, _pageIndex, _pageCount);
                    }
                    catch (Exception ex)
                    {
                        throw new CustomException(LocalizationProvider.GetLocalizedString("UCtrlPackageList_MsgBox_Msg_LoadPackages"), ex);
                    }

                    var dependonPackages = _projectManager.GetDependOnPackageInfos();//获取项目依赖包
                    foreach (var package in packages)
                    {
                        if (_obsNugetPackages.Where(o => o.Id == package.Id).ToList().Count > 0)
                            continue;

                        var packageStatus = WindowPackageManagement._currentPackageWrapList.Where(p => p.Id == package.Id).FirstOrDefault();//获取要执行的包

                        var nugetPackageWrap = new NugetPackageWrap(package);
                        if (dependonPackages != null)//已经安装
                        {
                            if (dependonPackages.Where(o => o.Id == nugetPackageWrap.Id).FirstOrDefault() != null)
                            {
                                nugetPackageWrap.StatusIcon = Visibility.Visible;
                            }
                        }

                        if (packageStatus != null)
                        {
                            nugetPackageWrap = changeImageStatus(nugetPackageWrap,packageStatus.PackageOperationType);
                           
                            nugetPackageWrap.ButtonIcon = Visibility.Visible;
                        }
                        //已安装的选项，如果项目依赖不存在则返回  不添加到列表
                        if (WindowPackageManagement.packagePageStatus == PackagePageStatus.installedPackageShow && dependonPackages.Where(o => o.Id == nugetPackageWrap.Id).FirstOrDefault() == null)
                        {
                            continue;
                        }
                        _obsNugetPackages.Add(nugetPackageWrap);
                    }
                }
            }
            catch (Exception ex)
            {
                LogHelper.Error(ex.ToString());
            }
            await this.Dispatcher.InvokeAsync(async () =>
            {
                await getPackageUpgradeAsync();
            }, System.Windows.Threading.DispatcherPriority.ApplicationIdle);
        }

        private void clearSearchBtn_Click(object sender, RoutedEventArgs e)
        {
            clearSearchTextBox();
        }
        private void clearSearchTextBox()
        {
            TextBox txtSearchBox = WPFExtensionMethods.FindVisualChild<TextBox>(FindName("txtSearch") as DependencyObject);
            txtSearchBox.Text = string.Empty;
        }
        public NugetPackageWrap Selection()
        {
            if (!string.IsNullOrWhiteSpace(_searchStr))
            {
                foreach (var package in _obsNugetPackages)
                {
                    if (package.Id.Contains(_searchStr))
                    {
                        this.lbPackages.SelectedItem = package;
                        return package;
                    }
                }
            }
            return null;
        }
        /// <summary>
        /// 包状态变更
        /// </summary>
        /// <param name="nugetPackageWrap"></param>
        /// <param name="packageOperationType"></param>
        /// <returns></returns>
        private NugetPackageWrap changeImageStatus(NugetPackageWrap nugetPackageWrap,PackageOperationType packageOperationType)
        {
            if (packageOperationType == PackageOperationType.UnInstall)
            {
                nugetPackageWrap.IsDelete = Visibility.Visible;
                nugetPackageWrap.IsUpdate = Visibility.Hidden;
                nugetPackageWrap.IsInstall = Visibility.Hidden;
            }
            else if (packageOperationType == PackageOperationType.Update)
            {
                nugetPackageWrap.IsUpdate = Visibility.Visible;
                nugetPackageWrap.IsDelete = Visibility.Hidden;
                nugetPackageWrap.IsInstall = Visibility.Hidden;
            }
            else if (packageOperationType == PackageOperationType.Install)
            {
                nugetPackageWrap.IsInstall = Visibility.Visible;
                nugetPackageWrap.IsUpdate = Visibility.Hidden;
                nugetPackageWrap.IsDelete = Visibility.Hidden;
            }
            return nugetPackageWrap;
        }

        public async Task<bool> getPackageUpgradeAsync()
        {
            bool change = false;
            var packages = await _nugetPackageManager.SearchPackagesAsync("", 0, 1000);
            
            var _nugetPackages = _obsNugetPackages.Where(o => o.UpgradeVersion == null).ToList();
            foreach (var package in _nugetPackages)
            {
                var packageWrapVer = new Version(package.Version);
                
                foreach (var ver in packages)
                {
                    var lastVer = new Version(ver.Version);
                    if (lastVer > packageWrapVer && package.StatusIcon == Visibility.Visible&& ver.Id == package.Id)
                    {
                        change = true;
                        _nugetPackages.Where(o => o.Id == package.Id).FirstOrDefault().IsUpgrade = Visibility.Visible;
                        _nugetPackages.Where(o => o.Id == package.Id).FirstOrDefault().UpgradeVersion = lastVer.ToString();
                        break;
                    }
                    else if (lastVer == packageWrapVer)
                    {
                        _nugetPackages.Where(o => o.Id == package.Id).FirstOrDefault().UpgradeVersion = lastVer.ToString();
                    }
                }
            }
            return change;
        }
        
    }
}